package com.bookmanger.interceptors;

import com.bookmanger.common.properties.JWTProperties;
import com.bookmanger.common.result.Result;
import com.bookmanger.utils.JwtUtil;
import com.bookmanger.utils.ThreadLocalUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.SignatureException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;
import java.util.Objects;


//拦截器，登录成功后的token存入redis
@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private JWTProperties jwtProperties;

    @Override //Intercepter(true/false)  ==true -> /user/login
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("JWT配置信息: secretKey=" + jwtProperties.getSecretKey() + 
                          ", tokenName=" + jwtProperties.getTokenName() + 
                          ", ttl=" + jwtProperties.getTtl());
        
        String token = request.getHeader("Authorization");
        // 如果Authorization头为空，尝试从配置的token名称中获取
        if (token == null || token.isEmpty()) {
            token = request.getHeader(jwtProperties.getTokenName());
        }

        // 如果仍然为空，返回401错误
        if (token == null || token.isEmpty()) {
            response.setStatus(401);
            System.err.println("请求中未提供JWT Token");
            return false;
        }

        System.out.println("接收到的Token: " + token);

        // 处理Bearer token格式
        if (token.startsWith("Bearer ")) {
            token = token.substring(7); // 去掉"Bearer "前缀
        }

        // 检查token格式是否正确（基本检查）
        if (!token.contains(".")) {
            response.setStatus(401);
            System.err.println("JWT Token格式不正确: " + token);
            return false;
        }

        //范型，如果不指定默认是Object
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        try {
            Claims claims = JwtUtil.parseJWT(jwtProperties.getSecretKey(), token);
            Map<String, Object> map = claims;
            String username = map.get("username").toString();
            String token2 = ops.get(username);
            if (!Objects.equals(token, token2)) {
                throw new RuntimeException("Token验证失败");
            }
            ThreadLocalUtil.set(map);
            return true;
        } catch (MalformedJwtException e) {
            response.setStatus(601);
            System.err.println("JWT格式错误: " + e.getMessage());
            return false;
        } catch (SignatureException e) {
            response.setStatus(602);
            System.err.println("JWT签名验证失败: " + e.getMessage());
            return false;
        } catch (ExpiredJwtException e) {
            response.setStatus(603);
            System.err.println("JWT已过期: " + e.getMessage());
            return false;
        } catch (UnsupportedJwtException e) {
            response.setStatus(604);
            System.err.println("不支持的JWT格式: " + e.getMessage());
            return false;
        } catch (IllegalArgumentException e) {
            response.setStatus(605);
            System.err.println("JWT为空: " + e.getMessage());
            return false;
        } catch (Exception e) {
            response.setStatus(606);
            System.err.println("Token解析异常: " + e.getMessage());
            return false;
        }

    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        ThreadLocalUtil.remove();//清除ThreadLocal 防止内存泄漏
    }

}